package com.uxsino.simo.collector.connections;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.security.cert.X509Certificate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

public class RestTemplateFactory {
    private static Logger logger = LoggerFactory.getLogger(RestTemplateFactory.class);

    static RestTemplate createRestTemplate(String protocol) {
        if (StringUtils.equalsIgnoreCase(protocol, "http")) {
            return createHttpRestTemplate();
        } else if (StringUtils.equalsIgnoreCase(protocol, "https")) {
            return createSSLRestTemplate();
        }
        return null;

    }

    static RestTemplate createHttpRestTemplate() {
        return new RestTemplate();
    }

    static RestTemplate createSSLRestTemplate() {
        RestTemplate restTemplate = null;

        try {
            restTemplate = new RestTemplate(createRequestFactory());
        } catch (Exception e) {
            logger.error("create https rest tempalte error", e);
        }
        return restTemplate;
    }

    public static MySimpleClientHttpRequestFactory createRequestFactory() {
        NullHostnameVerifier verifier = new NullHostnameVerifier();
        MySimpleClientHttpRequestFactory requestFactory = new MySimpleClientHttpRequestFactory(verifier);
        return requestFactory;
    }

    static class MySimpleClientHttpRequestFactory extends SimpleClientHttpRequestFactory {

        private final HostnameVerifier verifier;

        public MySimpleClientHttpRequestFactory(HostnameVerifier verifier) {
            this.verifier = verifier;
        }

        @Override
        protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws IOException {
            if (connection instanceof HttpsURLConnection) {
                ((HttpsURLConnection) connection).setHostnameVerifier(verifier);
                ((HttpsURLConnection) connection).setSSLSocketFactory(trustSelfSignedSSL().getSocketFactory());
                ((HttpsURLConnection) connection).setAllowUserInteraction(true);
            }
            super.prepareConnection(connection, httpMethod);
        }

        SSLContext trustSelfSignedSSL() {
            try {
                SSLContext ctx = SSLContext.getInstance("TLS");
                X509TrustManager tm = new X509TrustManager() {

                    public void checkClientTrusted(X509Certificate[] xcs, String string) {
                    }

                    public void checkServerTrusted(X509Certificate[] xcs, String string) {
                    }

                    public X509Certificate[] getAcceptedIssuers() {
                        return null;
                    }
                };
                ctx.init(null, new TrustManager[] { tm }, null);
                SSLContext.setDefault(ctx);
                return ctx;
            } catch (Exception ex) {
                logger.error("trust error", ex);
            }
            return null;
        }

    }

    static class NullHostnameVerifier implements HostnameVerifier {
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    }
}